/* Includes ------------------------------------------------------------------*/
#include "uart.h"
#include "main.h"

uint8_t 	USART1_Rx_BUF[USART1_RX_NUM];
uint8_t   USART1_Tx_BUF[USART1_TX_NUM];
Usart_TypeDef		usart1_var;			// USART1

/* Private functions ---------------------------------------------------------*/
/*****************************************************
**\brief      ASCII码转十六进制数字
*****************************************************/
uint32_t Ascii_To_Hex_Num(uint8_t* ascii, uint32_t len) 
{ 
	uint8_t i=0;
	uint32_t	ret=0;
	
	if(len > 9)return 0;
	
	for(; i<len; i++){
		if(ascii[i] == '.')continue;
		ret = ascii[i]-0x30+ret*10;
	}
	
	return	ret;
} 

/**
 * @brief 计算数组的两字节异或校验码
 * @param array 输入的数组（字节数组）
 * @param length 数组长度
 * @return 两字节的异或校验码（高字节为0，低字节为异或结果）
 */
uint16_t Ctl_CheckSum(const uint8_t *array, uint16_t length) 
{
	uint8_t checksum = 0;
	
	for(uint16_t i = 0; i < length; ++i){
		checksum ^= array[i]; // 逐字节异或
	}
	
	return (checksum & 0x0f); // 返回低字节为校验值，高字节为1
}

/**
 * @brief 计算数组的两字节异或校验码
 * @param array 输入的数组（字节数组）
 * @param length 数组长度
 * @return 两字节的异或校验码（高字节为0，低字节为异或结果）
 */
uint16_t Crt_CheckSum(const uint8_t *array, uint16_t length) 
{
	uint8_t checksum = 0;
	
	for(uint16_t i = 0; i < length; ++i){
		checksum += array[i]; // 逐字节异或
	}
	
	return checksum; // 返回低字节为校验值，高字节为1
}

/* Public functions ----------------------------------------------------------*/
/*****************************************************
**\brief      USART初始化函数
*****************************************************/
void Usart_Init(uint32_t usart_periph) 
{ 	
	uint32_t btr;
	
	if(usart_periph == USART1){
		rcu_periph_clock_enable(RCU_GPIOA);
		rcu_periph_clock_enable(RCU_USART1); 
		/* 使用 PA2 和 PA3 需配置为重映射 */
		gpio_init(USART1_TX_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, USART1_TX_PIN);
		gpio_init(USART1_RX_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, USART1_RX_PIN);
	}else	if(usart_periph == USART2){
		rcu_periph_clock_enable(RCU_GPIOC);
		rcu_periph_clock_enable(RCU_USART2); 
		/* 使用PC10和PC11需配置为重映射 */
		gpio_pin_remap_config(GPIO_USART2_PARTIAL_REMAP, ENABLE);	//使能 USART2 的 GPIO 引脚重映射
		gpio_init(USART2_TX_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, USART2_TX_PIN); 
		gpio_init(USART2_RX_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, USART2_RX_PIN); 
	}else if(usart_periph == UART4){
		
	}
	
	if(usart_periph == USART1){
		btr = 115200;
	}else if(usart_periph == UART4){
		btr = 9600;
	}
	
	/* USART配置 */
	usart_deinit(usart_periph);  // 复位USART 
	usart_baudrate_set(usart_periph, btr);  // 设置波特率
	usart_word_length_set(usart_periph, USART_WL_8BIT);  // 数据位为8位 
	usart_stop_bit_set(usart_periph, USART_STB_1BIT);  // 停止位为1位 
	usart_parity_config(usart_periph, USART_PM_NONE);  // 无校验位 
	usart_hardware_flow_rts_config(usart_periph, USART_RTS_DISABLE);  // 禁用RTS硬件流控制 
	usart_hardware_flow_cts_config(usart_periph, USART_CTS_DISABLE);  // 禁用CTS硬件流控制 
	usart_receive_config(usart_periph, USART_RECEIVE_ENABLE);  // 使能接收功能 
	usart_transmit_config(usart_periph, USART_TRANSMIT_ENABLE);  // 使能发送功能 
	
#ifdef	ENABLE_USART1_DMA0
	if(usart_periph == USART1)
		usart_interrupt_enable(usart_periph, USART_INT_IDLE);	//使能接收空闲中断
#elif defined DTS_CH4_IRDA_SSR	
	
#else
		usart_interrupt_enable(usart_periph, USART_INT_RBNE);	//使能接收中断
#endif
	/* 使能USART */ 
	usart_enable(usart_periph); 
} 

/*****************************************************
**\brief      DMA0 USART1接收配置
*****************************************************/
void Dma0_Usart1_Rx_Config(void)
{
	dma_parameter_struct dma_init_struct;
	// 使能DMA0时钟
	rcu_periph_clock_enable(RCU_DMA0);

	// 配置DMA通道5（USART1_RX）
	dma_deinit(DMA0, DMA_CH5);
	dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
	dma_init_struct.memory_addr = (uint32_t)USART1_Rx_BUF;
	dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
	dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
	dma_init_struct.number = USART1_RX_NUM;	                       
	dma_init_struct.periph_addr = (uint32_t)&USART_DATA(USART1);
	dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
	dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
	dma_init_struct.priority = DMA_PRIORITY_HIGH;
	dma_init(DMA0, DMA_CH5, &dma_init_struct);

	// 使能循环模式
	dma_circulation_enable(DMA0, DMA_CH5);
	// 使能DMA通道4
	dma_channel_enable(DMA0, DMA_CH5);
	// 绑定USART1_RX到DMA0通道5
	usart_dma_receive_config(USART1, USART_DENR_ENABLE);
	// 使能数据传输满中断
//	dma_interrupt_enable(DMA0, DMA_CH4, DMA_INT_FTF);
}

/*****************************************************
**\brief      串口DMA配置
**\param[in]  usart_periph: 串口号
*****************************************************/
void Uart_DMA_Config(uint32_t usart_periph)
{
	Usart_Init(usart_periph);
	if(usart_periph == USART1){
		Dma0_Usart1_Rx_Config();
	}
}

/*****************************************************
**\brief      USART1中断服务函数
*****************************************************/
void USART1_IRQHandler(void)
{
	if(RESET != usart_interrupt_flag_get(USART1, USART_INT_FLAG_IDLE)){	
//		PC_Data_Process(USART1_RX_NUM - dma_transfer_number_get(DMA0, DMA_CH5));	//数据处理
		usart_flag_get(USART1, USART_FLAG_IDLE);	//先读状态
		usart_data_receive(USART1);	//再读数据
		
		/* 重新配置 dma接收 */
		dma_channel_disable(DMA0, DMA_CH5);		// 关闭DMA传输
		dma_memory_address_config(DMA0, DMA_CH5, (uint32_t)USART1_Rx_BUF); // 重设一次内存地址
		dma_transfer_number_config(DMA0, DMA_CH5, USART1_RX_NUM);		// 重设一次搬运大小
		dma_channel_enable(DMA0, DMA_CH5);		// 开启DMA传输
	}
}

/*****************************************************
	\brief      UART 串口发送一个字节
	\param[in]  
	\arg        uart：串口号
	\arg        c   ：数据
*****************************************************/
void Usart_TxByte(uint32_t usart_periph, uint8_t data)
{
	usart_data_transmit(usart_periph, data);
	while(usart_flag_get(usart_periph, USART_FLAG_TBE) == RESET);
}

/*****************************************************
	\brief      UART 串口发送一个字节
	\param[in]  
	\arg        uart：串口号
	\arg        c   ：数据
*****************************************************/
void Usart_Tx_Buff(uint32_t usart_periph, uint8_t* data, uint16_t len)
{
	uint16_t i;
	
	for(i=0; i<len; i++){
		Usart_TxByte(usart_periph, data[i]);
	}
}

